/* This file is part of GSMC.
 * 
 * GSMC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GSMC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GSMC.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.hpxn.gsmc.action;

import java.util.ArrayList;

import net.hpxn.gsmc.config.map.Map.Mapping;
import net.hpxn.gsmc.core.event.BaseEvent;
import net.hpxn.gsmc.core.server.Server;
import net.hpxn.gsmc.core.server.ServerManager;
import net.hpxn.gsmc.core.server.exceptions.ServerCommunicationException;

/**
 * The base class that represents an action.
 * 
 * @author peterdi
 * 
 */
public abstract class BaseAction implements Runnable {

	private boolean isRunning;
	private BaseEvent event;
	private Mapping mapping;

	public BaseAction() {
		this.isRunning = true;
		this.event = null;
	}

	/**
	 * Override this method and do stuff!
	 */
	public abstract void run();

	/**
	 * Sets the current mapping for the action.
	 * 
	 * @param pMapping
	 *            - Mapping for the action.
	 */
	public void setMapping( Mapping pMapping ) {
		this.mapping = pMapping;
	}

	/**
	 * Sets the current event for the action.
	 * 
	 * @param Event
	 *            - Event this action is based on.
	 */
	public final void setEvent( BaseEvent pEvent ) {
		this.event = pEvent;
	}

	/**
	 * Sends a message to all servers listed in the config file.
	 * 
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToAll( String pMsg ) throws ServerCommunicationException {
		for ( Server wServer : ServerManager.getServerList() ) {
			wServer.sendRaw( pMsg );
		}
	}

	/**
	 * Sends a message to all servers listed in the config file except the one
	 * that triggered the current action.
	 * 
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToAllExceptCurrent( String pMsg ) throws ServerCommunicationException {
		for ( Server wServer : ServerManager.getServerList() ) {
			if ( !wServer.equals( this.event.getServer() ) ) {
				wServer.sendRaw( pMsg );
			}
		}
	}

	/**
	 * Sends a message to the server which the event came from.
	 * 
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToCurrent( String pMsg ) throws ServerCommunicationException {
		sendToOne( this.event.getServer(), pMsg );
	}

	/**
	 * Sends a message to a specific server. The first parameter is the server
	 * you want to send the message to. The second parameter is the message you
	 * want to send.
	 * 
	 * @param Server
	 *            - Server to message.
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToOne( Server pServer, String pMsg ) throws ServerCommunicationException {
		pServer.sendRaw( pMsg );
	}

	/**
	 * Sends a message to a specific group of servers.
	 * 
	 * @param int - Server group.
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToGroup( int pGroup, String pMsg ) throws ServerCommunicationException {
		for ( Server wServer : ServerManager.getServerList() ) {
			if ( wServer.getGroup() == pGroup ) {
				wServer.sendRaw( pMsg );
			}
		}
	}

	/**
	 * Sends a message to a specific group of servers. Except the the server
	 * that triggered the action.
	 * 
	 * @param int - Server group.
	 * @param String
	 *            - Message to send.
	 * @throws ServerCommunicationException 
	 */
	protected final void sendToGroupExceptCurrent( int pGroup, String pMsg ) throws ServerCommunicationException {
		for ( Server wServer : ServerManager.getServerList() ) {
			if ( wServer.getGroup() == pGroup ) {
				if ( !wServer.equals( this.event.getServer() ) ) {
					wServer.sendRaw( pMsg );
				}
			}
		}
	}

	/**
	 * Returns a boolean value if the action is still running.
	 * 
	 * @return boolean
	 */
	protected final boolean isRunning() {
		return this.isRunning;
	}

	/**
	 * Use this to stop the action if it requires to run for a specific amount
	 * of time.
	 * 
	 * @param boolean - Sets the action state.
	 */
	public final void setRunning( boolean isRunning ) {
		this.isRunning = isRunning;
	}

	/**
	 * Returns the list of servers that are configured in the configuration
	 * file. Use this list to determine what servers you want to message.
	 * 
	 * @return ArrayList<Server>
	 */
	protected final ArrayList<Server> getServerList() {
		return ServerManager.getServerList();
	}

	/**
	 * Returns the event object which is composed of information about the
	 * event. This is only included for convenience since most of the data is
	 * available through the BaseAction class.
	 * 
	 * @return Event
	 */
	public final BaseEvent getEvent() {
		if ( this.event != null ) {
			return this.event;
		}
		throw new RuntimeException( "Event must be set first." );
	}

	/**
	 * Returns the key of this mapping which is specified in the mapping file
	 * for this server type.
	 * 
	 * @return String
	 */
	public final String getMappingKey() {
		return mapping.getName();
	}
}
